August 02, 2021
문제 설명
한자리 숫자가 적힌 종이 조각이 흩어져있습니다. 흩어진 종이 조각을 붙여 소수를 몇 개 만들 수 있는지 알아내려 합니다.
각 종이 조각에 적힌 숫자가 적힌 문자열 numbers가 주어졌을 때, 종이 조각으로 만들 수 있는 소수가 몇 개인지 return 하도록 solution 함수를 완성해주세요.
제한사항
numbers는 길이 1 이상 7 이하인 문자열입니다. numbers는 0~9까지 숫자만으로 이루어져 있습니다. “013”은 0, 1, 3 숫자가 적힌 종이 조각이 흩어져있다는 의미입니다.
입출력 예
numbers | return |
---|---|
“17” | 3 |
“011” | 2 |
입출력 예 설명
예제 #1
[1, 7]으로는 소수 [7, 17, 71]를 만들 수 있습니다.
예제 #2
[0, 1, 1]으로는 소수 [11, 101]를 만들 수 있습니다.
11과 011은 같은 숫자로 취급합니다.
소수인지 찾는건 둘째치고… 일단 주어진 숫자로 몇 가지의 서로다른 숫자를 만들어낼 수 있는지부터 구해야한다.
이를 위해 순열
을 구하면 되는데… 이게 정말 힘들었다ㅠ 일단 파이썬에 쉽게 순열/조합을 구할 수 있는 모듈이 있어서 사용해보았다.
💡 파이썬 itertools 모듈
- product(p,q, …, [repeat=n]) : 데카르트 곱
- permutations(p, r) : p 중에서 r개를 뽑는 순열
- combinations(p, r) : p중에서 r개를 뽑는 조합
- combinationswithreplacement(p, r) : p중에서 r개를 뽑는 중복조합
파이썬 API 문서 참고
주의할 점은, 이 함수들은 generator
이다. 즉 루프를 돌며 한번 값을 던져주고 나면 그 값이 기억되지 않는다. 그렇기 때문에 이런 함수들을 쓰고 나서는 list() 등을 통해 iterator 객체에 값을 담아놔야 한다.
이 문제에서는 numbers에 같은 숫자가 들어있는 경우 중복 결과값이 나올 수도 있으니 set
에 넣어서 중복을 제거해주면 되겠다.
(itertools 모듈과 generator 개념에 대해서는 나중에 다시 자세하게 포스팅해야겠다)
만들 수 있는 모든 숫자들을 구했으면, 이제 이것들이 소수인지 아닌지 판별한다. 💎 n이 소수인지 판별할때는 1과 자신 외에 약수가 있는지 확인해보면 되는데, 약수를 구할때는 n의 제곱근까지만 확인해보면 된다!!
from itertools import permutations
import math
def solution(numbers):
result = set()
for r in range(1, len(numbers)+1):
for p in permutations(numbers, r):
result.add(int(''.join(p)))
# permutations는 generator 이기 때문에 루프 한번 돌고 결과값 사라짐
# set에 담기
answer = 0
for num in result:
check = 0
if num < 2:
check = 1 # 1이면 소수 아님
elif num == 2:
pass # 2이면 소수임
else:
for i in range(2, int(math.sqrt(num))+1):
if num % i == 0:
check = 1
break
if check == 0:
answer += 1
return answer
모듈을 사용하지 않고 순열을 구하기 위해 재귀함수를 사용하였다.
def permutation(numbers):
used = [0]*len(numbers) # 숫자 만들때 해당 숫자를 뽑았는지 안뽑았는지 표시하는 용도의 리스트(중복 선택 막기위해)
result = set() # numbers에 중복된 숫자 있는 경우 - set으로 정답 중복 제거
for r in range(1, len(numbers)+1):
# numbers 중 r개의 숫자 뽑은 모든 결과 구하는 함수
def generate(value, used):
# 재귀함수 종료조건: 만든 숫자의 길이가 r이 되면 종료
if len(value) == r:
result.add(int(value)) # int 변환 - 맨 앞자리 0 제거
return
# 재귀함수 본문
for i in range(len(numbers)):
if used[i] == 0:
value += numbers[i] # 숫자를 뽑아서 길이가 r이 될때까지 더해나간다
used[i] = 1 # 숫자 뽑을때 중복방지
generate(value, used)
# 재귀함수 종료후, 직전 상태로 되돌아가서 for문 마저 실행
value = value[:-1]
used[i] = 0
# 모든 r에 대해 generate 함수 수행
generate("", used)
return result
import math
# 최종 함수
def solution(numbers):
result = permutation(numbers)
return prime_number(result)
# 순열 구하는 함수
def permutation(numbers):
used = [0]*len(numbers)
result = set()
for r in range(1, len(numbers)+1):
def generate(value, used):
if len(value) == r:
result.add(int(value))
return
for i in range(len(numbers)):
if used[i] == 0:
value += numbers[i]
used[i] = 1
generate(value, used)
value = value[:-1]
used[i] = 0
generate("", used)
return result
# 소수 몇개인지 반환하는 함수
def prime_number(numbers):
answer = 0
for num in numbers:
check = 0
if num < 2:
check = 1
elif num == 2:
pass
else:
for i in range(2, int(math.sqrt(num))+1):
if num % i == 0:
check = 1
break
if check == 0:
answer += 1
return answer